package p2pscrabble;

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.Point;
import javax.swing.JComponent;
import javax.swing.TransferHandler;

public class MyTransferHandler extends javax.swing.TransferHandler {
	DataFlavor[] flavors;

	public MyTransferHandler() {
		flavors = new DataFlavor[] {
				new DataFlavor(LetterTile.class, "letter_tile"),
				new DataFlavor(LetterPanel.class, "letter_panel"),
				new DataFlavor(BoardTile.class, "board_tile"),
				new DataFlavor(BoardPanel.class, "board_panel") };
	}

	public boolean canImport(TransferSupport ts) {
		for (DataFlavor flavor : flavors) {
			if (ts.isDataFlavorSupported(flavor)) {
				return true;
			}
		}

		return false;
	}

	public boolean importData(TransferSupport ts) {
		LetterTile lt = null;
		try {
			lt = (LetterTile) ts.getTransferable().getTransferData(flavors[0]);
		} catch (java.io.IOException ex) {
			ex.printStackTrace();
		} catch (UnsupportedFlavorException ex) {
			ex.printStackTrace();
		}

		LetterPanel lp;
		BoardTile bt;

		Point source = lt.getLocation();

		int dropx = ts.getDropLocation().getDropPoint().x;
		int dropy = ts.getDropLocation().getDropPoint().y;
		dropx -= dropx % 27;
		dropy -= dropy % 27;
		
		if (ts.getComponent() instanceof LetterTile
				&& ((LetterTile) ts.getComponent()).isFixed()) {
			return false;
		}

		// source is on the board
		if (lt.isOnBoard()) {

			// target is letter panel (moving back the tiles)
			if ((ts.getComponent() instanceof LetterPanel)) {
				lp = (LetterPanel) ts.getComponent();
				if (dropy >= 54)
					dropy -= 27;
				lp.dropTileFromBoard(lt, dropx, dropy);
			}

			// swapping
			else if (ts.getComponent() instanceof LetterTile) {
				// swapping with other letter on the board
				if (ts.getComponent().getParent() instanceof BoardTile) {
					bt = (BoardTile) ts.getComponent().getParent();
					bt.setLetterTile(lt.getLetter(), lt.isBlank());

					((BoardPanel) bt.getParent()).setSwapChar(((LetterTile) ts
							.getComponent()).getLetter());
					((BoardPanel) bt.getParent()).setSwapBlank(((LetterTile) ts
							.getComponent()).isBlank());
				}
				// swapping with letter on hand
				if (ts.getComponent().getParent() instanceof LetterPanel) {
					lp = (LetterPanel) ts.getComponent().getParent();
					lp.swapTileFromBoard(lt.getLetter(), lt.isBlank(),
							((LetterTile) ts.getComponent()).getLocation());
					((GamePanel) lp.getParent()).setSwapChar(((LetterTile) ts
							.getComponent()).getLetter());
					((GamePanel) lp.getParent()).setSwapBlank(((LetterTile) ts
							.getComponent()).isBlank());
				}
			}
			// move to other empty tile on the board
			else if (ts.getComponent() instanceof BoardTile) {
				bt = (BoardTile) ts.getComponent();
				Point dest = bt.getLocation();
				((BoardPanel) bt.getParent()).setLetterTile(lt.getLetter(), lt
						.isBlank(), dest);
			} else {
				return false;
			}
		}

		// the source is from letter panel
		else {
			// target is letter panel
			if ((ts.getComponent() instanceof LetterPanel)) {
				lp = (LetterPanel) ts.getComponent();
				if (dropy >= 54)
					dropy -= 27;
				lp.dropTile(source, dropx, dropy);
				lp.setRemove(false);
			}

			// swapping
			else if (ts.getComponent() instanceof LetterTile) {
				// swapping with the one on the board
				if (ts.getComponent().getParent() instanceof BoardTile) {
					bt = (BoardTile) ts.getComponent().getParent();
					if (!bt.isEnabled())
						return false;
					bt.setLetterTile(lt.getLetter(), lt.isBlank());
					((GamePanel) bt.getParent().getParent())
							.setSwapChar(((LetterTile) ts.getComponent())
									.getLetter());
					((GamePanel) bt.getParent().getParent())
							.setSwapBlank(((LetterTile) ts.getComponent())
									.isBlank());
				}

				// swapping with other letter on hand
				if (ts.getComponent().getParent() instanceof LetterPanel) {
					Point dest = ts.getComponent().getLocation();
					lp = (LetterPanel) ts.getComponent().getParent();
					lp.swapTile(source, dest);
					lp.setRemove(false);
				}
			}

			// put the letter on the empty tile of the board
			else if (ts.getComponent() instanceof BoardTile) {
				bt = (BoardTile) ts.getComponent();
				if (!bt.isEnabled())
					return false;
				Point dest = bt.getLocation();
				((BoardPanel) bt.getParent()).setLetterTile(lt.getLetter(), lt
						.isBlank(), dest);
			}

			else {
				return false;
			}
		}

		return true;
	}

	protected void exportDone(JComponent source, Transferable data, int action) {
		LetterTile ltSource = (LetterTile) source;
		char swapChar = ' ';
		boolean swapBlank = false;

		// invalid drag n drop
		if (action == TransferHandler.NONE) {
			return;
		}

		// source is from board
		if (((LetterTile) source).isOnBoard()) {
			if (source.getParent() != null) {
				BoardTile btParent = (BoardTile) source.getParent();
				BoardPanel bpParent = null;

				bpParent = (BoardPanel) btParent.getParent();
				swapChar = ((GamePanel) bpParent.getParent()).getSwapChar();
				swapBlank = ((GamePanel) bpParent.getParent()).isSwapBlank();

				// swap letter on board with letter on hand
				if (swapChar != '/') {
					btParent.setLetterTile(swapChar, swapBlank);
					((GamePanel) bpParent.getParent()).setSwapChar('/');
				}

				// swap with other letter on board
				else if (((BoardPanel) btParent.getParent()).getSwapChar() != '/') {
					btParent.setLetterTile(((BoardPanel) btParent.getParent())
							.getSwapChar(), ((BoardPanel) btParent.getParent())
							.isSwapBlank());
					((BoardPanel) btParent.getParent()).setSwapChar('/');
				}

				// move from board to hand
				else if (btParent.getRemove()) {
					btParent.removeTile();
				}

				else {
					btParent.setRemove(true);
				}
			} else {
				source = null;
			}
		} else {
			LetterPanel lpParent = (LetterPanel) source.getParent();
			swapChar = ((GamePanel) lpParent.getParent()).getSwapChar();
			swapBlank = ((GamePanel) lpParent.getParent()).isSwapBlank();

			// swap letter on hand with letter on board
			if (swapChar != '/') {
				lpParent.swapTileFromBoard(swapChar, swapBlank, ltSource
						.getLocation());
				// System.out.println(swapChar);
				((GamePanel) lpParent.getParent()).setSwapChar('/');
			}

			// move from hand to board
			else if (lpParent.getRemove()) {
				lpParent.removeTile((LetterTile) source);
				lpParent.repaint();
			}

			else {
				lpParent.setRemove(true);
			}
		}
	}

	public int getSourceActions(JComponent cp) {
		if (cp instanceof LetterTile) {
			return MOVE;
		} else {
			return NONE;
		}
	}

	protected TileTransferable createTransferable(JComponent cp) {
		return new TileTransferable((LetterTile) cp);
	}

	class TileTransferable implements java.awt.datatransfer.Transferable {
		LetterTile lt;

		public TileTransferable(LetterTile lt) {
			this.lt = lt;
		}

		public Object getTransferData(DataFlavor fv)
				throws UnsupportedFlavorException {
			if (!isDataFlavorSupported(fv)) {
				throw new UnsupportedFlavorException(fv);
			}

			return lt;
		}

		public DataFlavor[] getTransferDataFlavors() {
			return flavors;
		}

		public boolean isDataFlavorSupported(DataFlavor fv) {
			for (DataFlavor flavor : flavors) {
				if (flavor.equals(fv)) {
					return true;
				}
			}

			return false;
		}
	}
}
